﻿using System;
using System.Threading;
using System.Windows;
using System.Windows.Threading;

namespace WpfThreadTest
{
    /// <summary>
    /// ThreadPoolDemo.xaml 的交互逻辑
    /// </summary>
    public partial class ThreadPoolDemo : Window
    {
        public ThreadPoolDemo()
        {
            InitializeComponent();
            ///设置线程池的最大可用辅助线程数目，最大异步线程数目
            ThreadPool.SetMaxThreads(100, 10);

        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            //调用线程去计算数字，仅供演示
            ThreadPool.QueueUserWorkItem(new WaitCallback(CountNumber), 1);
        }
        private void CountNumber(object state)
        {
            int count = int.Parse(state.ToString());
            while (true)
            {
                count++;
                this.textBlock2.Dispatcher.Invoke(
                    DispatcherPriority.Normal,
                    new Action(() =>
                    {
                        this.textBlock2.Text = count.ToString();
                    }));
                Thread.Sleep(100);
            }
        }
        /// <summary>
        /// 测试线程中传递引用对象，以期望获得返回值
        /// </summary>
        /// <param name="state"></param>
        private void ReturnValueMethod(object state)
        {
            MyParam myParam = state as MyParam;
            myParam.MyInt = 100;
            myParam.MyString = "updated string";
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            ///将引用对象传递给线程
            MyParam myParam = new MyParam() { MyInt = 12, MyString = "test" };

            ThreadPool.QueueUserWorkItem(new WaitCallback(ReturnValueMethod), myParam);

            ///主线程睡眠5ms后，再去读取对象的值
            ///如果不睡眠，直接读取，可能读不到修改后的值，因为他们处于不同的线程当中
            ///当主线程去读取时，子线程尚未更改,
            ///即便如此，也会有读取不到的时候，故此种传值方式并不十分可取，
            ///具体线程返回值可以参考MSDN http://msdn.microsoft.com/zh-cn/library/wkays279.aspx
            Thread.Sleep(5);
            this.textBlock1.Text = string.Format("MyInt:{0},MyString:{1}", myParam.MyInt, myParam.MyString);
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetThreadPoolInfo), null);
        }
        private void GetThreadPoolInfo(object state)
        {
            while (true)
            {
                int workerThreads = 0;
                int completionPortThreads = 0;
                ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
                this.textBlock3.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() =>
                {
                    this.textBlock3.Text =
                        string.Format("池中可用辅助线程：{0},可用异步 I/O 线程：{1}",
                        workerThreads, completionPortThreads);
                }));
                Thread.Sleep(1000);
            }
        }
    }
    public class MyParam
    {
        public int MyInt { get; set; }
        public string MyString { get; set; }
    }
}